// Assets/copy_script.js
// 功能：渲染网站/账号/密码列（密码为固定 8 个圆点占位）
// 自动静默尝试加载 file:///D:/HTML/Bookmarks/Assets/wzmm.js；失败则页面仍展示网站+账号+固定占位。
// 点击密码未加载时提示用户去按“显示 / 隐藏”手动导入；按住“显示/隐藏”会先尝试自动加载（静默），若失败弹文件选择手动导入。
// 手动导入成功后仅密码处短暂 5s 显示明文，然后恢复掩码。
// 导入成功/失败提示为“替换式提示”（后到的提示直接覆盖前面的提示）。

$(function() {
	var $section = $('.section');

	// 配置
	var SPEEDS = {
		site: 500,
		account: 1200,
		password: 2000
	};
	var MASK_LENGTH = 8;
	var CLEAR_SHOW_MS = 5000; // 手动导入成功后密码短暂展示时长(ms)
	var AUTO_WZMM_PATH = "file:///D:/HTML/Bookmarks/Assets/wzmm.js";

	// 状态
	var passwordMap = {}; // id -> plaintext
	var mmLoaded = !!window.__WZMM_LOADED__;

	// ---- 替换式单条提示（后到的提示会立即覆盖前一条） ----
	var $singleNotice = null;
	var noticeTimer = null;

	function showReplacingNotice(msg, ms) {
		ms = ms || 5000;
		if (!$singleNotice) {
			$singleNotice = $('<div id="__single_notice"></div>').css({
				position: 'fixed',
				left: '50%',
				top: '15%',
				transform: 'translateX(-50%)',
				padding: '8px 12px',
				borderRadius: '6px',
				background: 'rgba(0,0,0,0.75)',
				color: '#fff',
				zIndex: 99999,
				fontSize: '14px',
				display: 'none',
				whiteSpace: 'nowrap',
				letterSpacing: '0'
			}).appendTo('body');
		}
		// Try to use existing page toast DOM if present (replace instead)
		var known = ['.toast', '#toast', '.tip', '#tip', '.notice', '#notice', '.message', '#message',
			'.copy-tip', '#copy-tip'
		];
		for (var i = 0; i < known.length; i++) {
			var $el = $(known[i]);
			if ($el.length) {
				$el.stop(true, true).text(msg).show();
				clearTimeout(noticeTimer);
				noticeTimer = setTimeout(function() {
					$el.fadeOut(200);
				}, ms);
				return;
			}
		}
		// fallback single notice
		$singleNotice.stop(true, true).text(msg).fadeIn(120);
		clearTimeout(noticeTimer);
		noticeTimer = setTimeout(function() {
			$singleNotice.fadeOut(200);
		}, ms);
	}

	// ---- 解密支持 ----
	function decryptCipher(cipherText) {
		if (!cipherText) return '';
		try {
			if (typeof decryptPwd === 'function') {
				return decryptPwd(cipherText) || '';
			}
			if (typeof CryptoJS !== 'undefined') {
				var AES_KEY = CryptoJS.enc.Utf8.parse("pmkt25y27gbjed5sdsazbkvo81t56344");
				var ct = CryptoJS.enc.Base64.parse(cipherText);
				var dec = CryptoJS.AES.decrypt({
					ciphertext: ct
				}, AES_KEY, {
					mode: CryptoJS.mode.ECB,
					padding: CryptoJS.pad.Pkcs7
				});
				return dec.toString(CryptoJS.enc.Utf8) || '';
			}
		} catch (e) {
			console.error('decrypt error', e);
		}
		return '';
	}

	// ---- 从 window.wzmm 构建 map ----
	function buildPasswordMapFromWzmm() {
		passwordMap = {};
		try {
			if (Array.isArray(window.wzmm)) {
				window.wzmm.forEach(function(entry) {
					var id = entry.id || entry.ID || (entry[0] && String(entry[0])) || '';
					var cipher = entry.pwd || entry.password || entry[1] || '';
					if (!id) return;
					var plain = decryptCipher(cipher);
					if (plain) passwordMap[id] = plain;
				});
			}
		} catch (e) {
			console.error('buildPasswordMapFromWzmm error', e);
			passwordMap = {};
		}
	}

	// ---- 更新页面上密码元素的数据 (不重建整个列表) ----
	function updatePasswordElements() {
		$section.find('.copy-text.pwd').each(function() {
			var $a = $(this);
			var id = $a.attr('data-id') || '';
			var plain = passwordMap[id] || '';
			$a.attr('data-copy', plain);
			// always display fixed MASK_LENGTH bullets when masked
			if (!plain) {
				$a.text('•'.repeat(MASK_LENGTH)).attr('data-mask', 'true');
			} else {
				$a.text('•'.repeat(MASK_LENGTH)).attr('data-mask', 'true');
			}
		});
	}

	// ---- 渲染列表（总是渲染网站和账号；密码列显示占位或真实数据） ----
	function renderSites() {
		var sites = window.wzxx || (typeof getWebsiteData === 'function' ? getWebsiteData() : []);
		if (!Array.isArray(sites)) sites = [];

		var $nigiri = $section.find('dl.list.nigiri').empty().append('<dt>网站（点击可访问）</dt>');
		var $maki = $section.find('dl.list.maki.copy').empty().append('<dt>账号（点击可复制）</dt>');
		var $sashimi = $section.find('dl.list.sashimi.copy').empty().append('<dt>密码（点击可复制）</dt>');

		sites.forEach(function(s) {
			// 网站
			var $siteA = $('<a>').attr({
				href: s.url || '#',
				target: '_blank'
			}).text(s.name || '-');
			$('<dd>').append($siteA).hide().appendTo($nigiri).slideDown(SPEEDS.site);

			// 账号
			var accVal = s.account == null ? '' : String(s.account);
			var $accA = $('<a>').attr({
				href: '#',
				'data-copy': accVal
			}).addClass('copy-text acc').text(accVal || '-');
			$('<dd>').append($accA).hide().appendTo($maki).slideDown(SPEEDS.account);

			// 密码（固定 MASK_LENGTH 占位；如果 passwordMap 已有则 data-copy 填充）
			var $pwdA = $('<a>').attr({
				href: '#',
				'data-copy': '',
				'data-id': s.id || '',
				'data-mask': 'true',
				style: 'letter-spacing:0' // tighten dots, harmless inline style
			}).addClass('copy-text pwd');

			var plain = (s.id && passwordMap[s.id]) ? passwordMap[s.id] : '';
			if (plain) {
				$pwdA.attr('data-copy', plain).text('•'.repeat(MASK_LENGTH));
			} else {
				$pwdA.text('•'.repeat(MASK_LENGTH));
			}
			$('<dd>').append($pwdA).hide().appendTo($sashimi).slideDown(SPEEDS.password);
		});
	}

	// ---- 复制工具 ----
	function copyTextToClipboard(text) {
		if (!text) return Promise.reject(new Error('empty'));
		if (navigator.clipboard && window.isSecureContext) {
			return navigator.clipboard.writeText(text);
		} else {
			return new Promise(function(resolve, reject) {
				var $ta = $('<textarea>').css({
					position: 'absolute',
					left: '-9999px',
					top: 0
				}).val(text).appendTo('body').select();
				try {
					document.execCommand('copy');
					$ta.remove();
					resolve();
				} catch (e) {
					$ta.remove();
					reject(e);
				}
			});
		}
	}

	// ---- mask / reveal ----
	function maskPasswords() {
		$section.find('.copy-text.pwd').each(function() {
			var $a = $(this);
			var val = $a.attr('data-copy') || '';
			$a.text('•'.repeat(MASK_LENGTH)).attr('data-mask', 'true');
		});
	}

	function revealPasswords() {
		$section.find('.copy-text.pwd').each(function() {
			var $a = $(this);
			var val = $a.attr('data-copy') || '';
			if (val) $a.text(val).attr('data-mask', 'false');
		});
	}

	// ---- 自动静默加载 wzmm.js（不提示） ----
	function tryLoadWzmmSilent() {
		return new Promise(function(resolve, reject) {
			if (window.__WZMM_LOADED__) {
				resolve(true);
				return;
			}
			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = AUTO_WZMM_PATH;
			script.onload = function() {
				// build password map but DO NOT show any notice or reveal
				try {
					buildPasswordMapFromWzmm();
					window.__WZMM_LOADED__ = true;
					mmLoaded = true;
					updatePasswordElements();
					resolve(true);
				} catch (e) {
					console.error('wzmm onload error', e);
					reject(e);
				}
			};
			script.onerror = function() {
				// fail silently (no notice)
				reject(new Error('auto load failed'));
			};
			document.head.appendChild(script);
		});
	}

	// ---- 手动导入 wzmm.js（弹文件选择），导入成功后覆盖提示并短暂展示密码 ----
	function manualImportWzmmWithPrompt() {
		return new Promise(function(resolve, reject) {
			showReplacingNotice('请导入wzmm.js文件，文件位于【D:/HTML/Bookmarks/Assets】或FTP根目录下相同路径', 15000);
			var $input = $('<input type="file" accept=".js">').css({
				display: 'none'
			}).appendTo('body');
			$input.on('change', function(e) {
				var file = e.target.files[0];
				if (!file) {
					showReplacingNotice('未选择文件', 3000);
					$input.remove();
					reject(new Error('no file'));
					return;
				}
				var reader = new FileReader();
				reader.onload = function(evt) {
					try {
						// eval in global scope
						(0, eval)(evt.target.result);
						buildPasswordMapFromWzmm();
						window.__WZMM_LOADED__ = true;
						mmLoaded = true;
						updatePasswordElements();
						showReplacingNotice('wzmm.js 导入成功', 3000);
						// 仅密码处短暂显示明文
						revealPasswords();
						setTimeout(function() {
							maskPasswords();
						}, CLEAR_SHOW_MS);
						$input.remove();
						resolve(true);
					} catch (err) {
						console.error('manual import err', err);
						showReplacingNotice('wzmm.js 导入失败: ' + (err.message || err), 4000);
						$input.remove();
						reject(err);
					}
				};
				reader.readAsText(file, 'utf-8');
			});
			$input.trigger('click');
		});
	}

	// ---- 事件：点击复制 ----
	$section.on('click', '.copy-text', function(e) {
		e.preventDefault();
		var $this = $(this);
		var isPwd = $this.hasClass('pwd');
		var text = $this.attr('data-copy') || '';

		if (isPwd && !mmLoaded) {
			// 指导用户去按显示/隐藏按钮导入（不自动弹窗）
			showReplacingNotice(
				'请点击页面下方【显示/隐藏】按钮导入wzmm.js 以显示密码', 6000);
			return;
		}

		if (!text) {
			showReplacingNotice('无可复制内容', 2000);
			return;
		}

		copyTextToClipboard(text).then(function() {
			showReplacingNotice('已复制: ' + text, 2000);
		}).catch(function() {
			showReplacingNotice('复制失败', 2000);
		});
	});

	// ---- 按钮：按住尝试自动加载（静默）-> 失败则弹手动导入；导入成功后仅密码显示 5s ----
	var $toggle = $section.find('a.toggle');
	$toggle.on('mousedown touchstart', function(e) {
		e.preventDefault();
		if (mmLoaded) {
			revealPasswords();
			return;
		}
		// 先静默尝试自动加载
		tryLoadWzmmSilent().then(function() {
			// 自动加载成功: updatePasswordElements() already called inside; now briefly show plaintext for CLEAR_SHOW_MS
			showReplacingNotice('wzmm.js 自动导入成功',
				2500
			); // user requested automatic success no prompt — but they earlier said no prompt; user now earlier: "自动加载wzmm.js成功不用展示5秒明文密码，且不需要任何提示" -> So remove this line. 
		}).catch(function() {
			// 自动加载失败 -> 弹手动导入，且手动导入会 showReplacingNotice success/fail
			manualImportWzmmWithPrompt().catch(function() {
				/* ignore */
			});
		}).finally(function() {
			// In all cases, reveal temporarily only if mmLoaded became true
			if (mmLoaded) {
				revealPasswords();
				setTimeout(function() {
					maskPasswords();
				}, CLEAR_SHOW_MS);
			}
		});
	});

	// We must adjust per your preference: AUTOMATIC success should be silent WITHOUT any notice or 5s reveal.
	// The above code currently shows a notice on auto success; remove that to satisfy "自动加载成功无提示、无 5s 展示".
	// So let's correct: override tryLoadWzmmSilent to not call showReplacingNotice on success, and ensure we do NOT reveal on auto success.
	// To do that, we'll rewrite the call here to reflect silent auto-success behavior:
	$toggle.off('mousedown touchstart'); // remove the above handler
	$toggle.on('mousedown touchstart', function(e) {
		e.preventDefault();
		if (mmLoaded) {
			revealPasswords();
			return;
		}
		// silent auto load: if success -> just update password elements (no notice, no reveal)
		tryLoadWzmmSilent().then(function() {
			// auto success: passwordMap updated, updatePasswordElements already called in tryLoadWzmmSilent
			// per requirement: do NOT show notice and do NOT reveal for 5s
			// but user expects on manual import success to show 5s and to show notice
			// so here do nothing besides ensuring password data available
		}).catch(function() {
			// auto failed -> now open manual import and manualImportWzmmWithPrompt will show notice and reveal 5s
			manualImportWzmmWithPrompt().catch(function() {
				/* ignore */
			});
		}).finally(function() {
			// if mmLoaded now (i.e. auto succeeded previously or manual succeeded), then reveal for 5s only if manualImport triggered success path
			if (mmLoaded) {
				// If we reached here because manualImport succeeded, manualImport already did reveal+mask.
				// If mmLoaded became true due to silent auto, do NOT reveal (per requirement).
				// So do nothing here.
			}
		});
	});

	// 松开后掩码（只有在 mmLoaded 情况下才有真实密码）
	$(document).on('mouseup touchend touchcancel', function() {
		if (mmLoaded) maskPasswords();
	});
	$toggle.on('mouseleave', function() {
		if (mmLoaded) maskPasswords();
	});

	$toggle.on('keydown', function(e) {
		if (e.key === ' ' || e.key === 'Enter') {
			e.preventDefault();
			// emulate mousedown behavior
			if (mmLoaded) {
				revealPasswords();
				return;
			}
			tryLoadWzmmSilent().then(function() {
				// silent success -> nothing
			}).catch(function() {
				manualImportWzmmWithPrompt().catch(function() {
					/* ignore */
				});
			});
		}
	});
	$toggle.on('keyup', function(e) {
		if (e.key === ' ' || e.key === 'Enter') {
			if (mmLoaded) maskPasswords();
		}
	});

	// ---- 启动：渲染站点（不依赖 wzmm）并静默尝试一次自动加载（不提示、不 reveal） ----
	renderSites();
	tryLoadWzmmSilent().then(function() {
		// silent success: updatePasswordElements already called inside; per requirement do NOT show any notice nor reveal 5s
	}).catch(function() {
		// silent failure: do nothing (renderSites already rendered fixed-mask)
	});
});


// 以下为新代码

// ========== wzqt 动画展开速度配置（不会影响原有 SPEEDS） ==========
var SPEEDS_QT = {
	site: 500, // 网站列展开时间（优先用这个）
	account: 1200, // 账号列展开时间
	password: 2000 // 密码列展开时间
};

// 获取动画速度（优先 SPEEDS_QT，其次 SPEEDS，全无则默认 800）
function getQtSpeed(key) {
	if (SPEEDS_QT && typeof SPEEDS_QT[key] === "number" && SPEEDS_QT[key] > 0) {
		return SPEEDS_QT[key];
	}
	if (typeof SPEEDS !== "undefined" && SPEEDS && typeof SPEEDS[key] === "number" && SPEEDS[key] > 0) {
		return SPEEDS[key];
	}
	return 800;
}

// ========== wzqt 文字显示时机配置 ==========
var SHOW_DELAYS_QT = {
	site: 0.5, // 在动画进度 50% 时显示文字
	account: 0.5,
	password: 0.5
};

// 获取文字显示时机（比例），优先 SHOW_DELAYS_QT，再回退 SHOW_DELAYS
function getQtShowDelay(key) {
	if (SHOW_DELAYS_QT && typeof SHOW_DELAYS_QT[key] === "number" && SHOW_DELAYS_QT[key] > 0) {
		return SHOW_DELAYS_QT[key];
	}
	if (typeof SHOW_DELAYS !== "undefined" && SHOW_DELAYS && typeof SHOW_DELAYS[key] === "number" && SHOW_DELAYS[key] >
		0) {
		return SHOW_DELAYS[key];
	}
	return 0.5; // 默认在动画 50% 时显示文字
}

// ========== wzqt 数据渲染（带展开动画 & 延迟文字显示） ==========
$(window).on("load", function() {
	if (!Array.isArray(window.wzqt) || !wzqt.length) return;

	var $section = $(".section");
	var $nigiri = $section.find("dl.list.nigiri");
	var $maki = $section.find("dl.list.maki.copy");
	var $sashimi = $section.find("dl.list.sashimi.copy");

	wzqt.forEach(function(item, idx) {
		var id = item.id || "";
		var url = item.url || "#";
		var name = item.name || "-";
		var notes = item.notes || "-";
		var content = (typeof item.content === "string") ? item.content : String(item.content || "");

		// === 网站列 ===
		var $siteDD = $("<dd>").hide();
		var $siteA = $("<a>").attr({
			href: url,
			target: "_blank"
		}).css("visibility", "hidden");
		$siteDD.append($siteA).appendTo($nigiri);

		var siteSpeed = getQtSpeed("site");
		$siteDD.slideDown(siteSpeed);
		setTimeout(function() {
			$siteA.text(name).css("visibility", "visible");
		}, siteSpeed * getQtShowDelay("site"));

		// === 账号列 ===
		var $accDD = $("<dd>").hide();
		var $accA = $("<a>")
			.attr({
				href: "#",
				"data-copy": content
			})
			.addClass("copy-text acc")
			.css("visibility", "hidden");
		$accDD.append($accA).appendTo($maki);

		var accSpeed = getQtSpeed("account");
		$accDD.slideDown(accSpeed);
		setTimeout(function() {
			$accA.text(notes).css("visibility", "visible");
		}, accSpeed * getQtShowDelay("account"));

		// === 密码列 ===
		var $pwdDD = $("<dd>").hide();
		var $pwdA;
		var pwdObj = (Array.isArray(window.wzmm)) ? wzmm.find(p => p.id === id) : null;

		if (pwdObj) {
			// 有对应密码 → 可复制
			$pwdA = $("<a>")
				.attr({
					href: "#",
					"data-id": id,
					"data-copy": "",
					"data-mask": "true"
				})
				.addClass("copy-text pwd")
				.css("visibility", "hidden");
		} else {
			// 无对应密码 → 占位
			$pwdA = $("<a>")
				.attr({
					href: "javascript:void(0);"
				})
				.addClass("copy-text pwd disabled")
				.css("visibility", "hidden");
		}

		$pwdDD.append($pwdA).appendTo($sashimi);

		var pwdSpeed = getQtSpeed("password");
		$pwdDD.slideDown(pwdSpeed);
		setTimeout(function() {
			$pwdA.text("•".repeat(8)).css("visibility", "visible");
		}, pwdSpeed * getQtShowDelay("password"));
	});

	// 更新密码（原逻辑）
	if (typeof updatePasswordElements === "function") {
		updatePasswordElements();
	}
});